package com.hrt.serial.modbus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.btcode.common.BitType;
import com.btcode.common.ByteUnit;
import com.hrt.datasender.datacollect.drive.DriveConfigModel;

/**
 * modbus数据解析类
 * 
 * @author gislin
 */
public class ModbusDataDecodeTCP extends ModbusDataDecode {
    /**
     * 报文前缀长度，6位MBAP,1位从站编号，1位功能码，1位数据长度
     */
    private final int msgPrefixLength = 9;   
    private final int dataLengthBytePos = 8;

    /**
     * 
     * @param data
     * @param byteLength
     * @return
     */
    public synchronized List<ModbusDataModel> dataModelDecode(byte[] data, int byteLength, DriveConfigModel deviceConfigs) {
        HashMap<String, String> configsMap = deviceConfigs.getConfig();
        BitType bitType = getBitType(configsMap.get("dataBit"));
        List<ModbusDataModel> models = null;
        byte[] finalByteData = mergeData(data, byteLength);

        ModbusDataFrameDecoderBase modbusMsgModel = new ModbusDataFrameDecoderTCP(finalByteData);

        do {
            try {
                finalByteData = modbusMsgModel.next();
            }
            catch (MsgLengthException e) {
                byte[] leftMsg = modbusMsgModel.getLeftMsg();
                setTempByteData(leftMsg, leftMsg.length);
                break;
            }
            catch (CRCException e) {
                break;
            }

            models = new ArrayList<>();

            String mn = ByteUnit.ConvertByteToInt8(finalByteData[0]) + "";
            /**
             * 整个报文中，数据部分的字节长度 BitType.bit16：两个字节代表一个数据 BitType.bit32：四个字节代表一个数据
             * 所以数据字节长度和真正的业务数据长度不一样 数据字节长度和业务数据有倍数关系
             */
            int dataLength = ByteUnit.ConvertByteToInt8(finalByteData[dataLengthBytePos]) / bitType.byteLength;

            double[] resultData = new double[dataLength];

            for (int i = 0; i < dataLength; i++) {
                /**
                 * 这里加9是因为，前6位是MBAP，第七位是mn，第八位是功能码，第九位是数据长度，所以从第十位开始算起
                 */
                byte[] dataItem = new byte[bitType.byteLength];
                System.arraycopy(finalByteData, msgPrefixLength + i * bitType.byteLength, dataItem, 0, bitType.byteLength);

                double value = ByteUnit.ConvertByteToDoubleX(dataItem, bitType);
                resultData[i] = value;
            }

            ModbusDataModel model = new ModbusDataModel();
            model.setData(resultData);
            model.setDataLength(dataLength);
            model.setId(mn);
            model.setSourceData(finalByteData);

            models.add(model);
        } while (true);

        return models;

    }

    @Override
    public ModbusDataFrameDecoderBase getDataFrameDecoder(byte[] finalByteData) {
        ModbusDataFrameDecoderBase modbusMsgModel = new ModbusDataFrameDecoderTCP(finalByteData);
        return modbusMsgModel;
    }

}
